{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "a55e7a0c",
   "metadata": {},
   "source": [
    "# NumPy 数组迭代\n",
    "## 数组迭代\n",
    "迭代意味着逐一遍历元素。\n",
    "\n",
    "当我们在 numpy 中处理多维数组时，可以使用 python 的基本 for 循环来完成此操作。\n",
    "\n",
    "如果我们对 1-D 数组进行迭代，它将逐一遍历每个元素。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "b7bb841e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "\n",
    "arr = np.array([1, 2, 3])\n",
    "\n",
    "for x in arr:\n",
    "  print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3fbfa321",
   "metadata": {},
   "source": [
    "## 迭代 2-D 数组\n",
    "在 2-D 数组中，它将遍历所有行。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "2f897564",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 2 3]\n",
      "[4 5 6]\n"
     ]
    }
   ],
   "source": [
    "arr = np.array([[1, 2, 3], [4, 5, 6]])\n",
    "\n",
    "for x in arr:\n",
    "  print(x)\n",
    "# 如果我们迭代一个 n-D 数组，它将逐一遍历第 n-1 维"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "64611a0b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "6\n"
     ]
    }
   ],
   "source": [
    "# 如需返回实际值、标量，我们必须迭代每个维中的数组\n",
    "arr = np.array([[1, 2, 3], [4, 5, 6]])\n",
    "\n",
    "for x in arr:\n",
    "  for y in x:\n",
    "    print(y)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "32401987",
   "metadata": {},
   "source": [
    "## 迭代 3-D 数组\n",
    "在 3-D 数组中，它将遍历所有 2-D 数组。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "0adc1ad7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2 3]\n",
      " [4 5 6]]\n",
      "[[ 7  8  9]\n",
      " [10 11 12]]\n"
     ]
    }
   ],
   "source": [
    "arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])\n",
    "\n",
    "for x in arr:\n",
    "  print(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "aefbdb23",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "6\n",
      "7\n",
      "8\n",
      "9\n",
      "10\n",
      "11\n",
      "12\n"
     ]
    }
   ],
   "source": [
    "# 要返回实际值、标量，我们必须迭代每个维中的数组\n",
    "arr = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])\n",
    "\n",
    "for x in arr:\n",
    "  for y in x:\n",
    "    for z in y:\n",
    "      print(z)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7ad77eeb",
   "metadata": {},
   "source": [
    "## 使用 nditer() 迭代数组\n",
    "函数 nditer() 是一个辅助函数，从非常基本的迭代到非常高级的迭代都可以使用。它解决了我们在迭代中面临的一些基本问题，让我们通过例子进行介绍。\n",
    "\n",
    "### 迭代每个标量元素\n",
    "在基本的 for 循环中，迭代遍历数组的每个标量，我们需要使用 n 个 for 循环，对于具有高维数的数组可能很难编写。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "833b9dd0",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "2\n",
      "3\n",
      "4\n",
      "5\n",
      "6\n",
      "7\n",
      "8\n"
     ]
    }
   ],
   "source": [
    "arr = np.array([[[1, 2], [3, 4]], [[5, 6], [7, 8]]])\n",
    "\n",
    "for x in np.nditer(arr):\n",
    "  print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "4b4e210d",
   "metadata": {},
   "source": [
    "## 迭代不同数据类型的数组\n",
    "我们可以使用 op_dtypes 参数，并传递期望的数据类型，以在迭代时更改元素的数据类型。\n",
    "\n",
    "NumPy 不会就地更改元素的数据类型（元素位于数组中），因此它需要一些其他空间来执行此操作，该额外空间称为 buffer，为了在 nditer() 中启用它，我们传参 flags=['buffered']。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "0842af49",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "b'1'\n",
      "b'2'\n",
      "b'3'\n"
     ]
    }
   ],
   "source": [
    "arr = np.array([1, 2, 3])\n",
    "\n",
    "for x in np.nditer(arr, flags=['buffered'], op_dtypes=['S']):\n",
    "  print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b16d3ec6",
   "metadata": {},
   "source": [
    "## 以不同的步长迭代\n",
    "我们可以使用过滤，然后进行迭代。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "c9f89114",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n",
      "3\n",
      "5\n",
      "7\n"
     ]
    }
   ],
   "source": [
    "# 每遍历 2D 数组的一个标量元素，跳过 1 个元素\n",
    "arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])\n",
    "\n",
    "for x in np.nditer(arr[:, ::2]):\n",
    "  print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f31e5350",
   "metadata": {},
   "source": [
    "## 使用 ndenumerate() 进行枚举迭代\n",
    "枚举是指逐一提及事物的序号。\n",
    "\n",
    "有时，我们在迭代时需要元素的相应索引，对于这些用例，可以使用 ndenumerate() 方法。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "a81c07fa",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(0,) 1\n",
      "(1,) 2\n",
      "(2,) 3\n"
     ]
    }
   ],
   "source": [
    "arr = np.array([1, 2, 3])\n",
    "\n",
    "for idx, x in np.ndenumerate(arr):\n",
    "  print(idx, x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "eb6d9e11",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(0, 0) 1\n",
      "(0, 1) 2\n",
      "(0, 2) 3\n",
      "(0, 3) 4\n",
      "(1, 0) 5\n",
      "(1, 1) 6\n",
      "(1, 2) 7\n",
      "(1, 3) 8\n"
     ]
    }
   ],
   "source": [
    "arr = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])\n",
    "\n",
    "for idx, x in np.ndenumerate(arr):\n",
    "  print(idx, x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "df503225",
   "metadata": {},
   "source": [
    "# NumPy 数组连接\n",
    "## 连接 NumPy 数组\n",
    "连接意味着将两个或多个数组的内容放在单个数组中。\n",
    "\n",
    "在 SQL 中，我们基于键来连接表，而在 NumPy 中，我们按轴连接数组。\n",
    "\n",
    "我们传递了一系列要与轴一起连接到 concatenate() 函数的数组。如果未显式传递轴，则将其视为 0。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "id": "f67b2b32",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2]\n",
      " [3 4]\n",
      " [5 6]\n",
      " [7 8]] (4, 2)\n"
     ]
    }
   ],
   "source": [
    "arr1 = np.array([[1, 2], [3, 4]])\n",
    "arr2 = np.array([[5, 6], [7, 8]])\n",
    "\n",
    "arr = np.concatenate((arr1, arr2))\n",
    "print(arr, arr.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "id": "592b7bee",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2 5 6]\n",
      " [3 4 7 8]] (2, 4)\n"
     ]
    }
   ],
   "source": [
    "# 沿着行 (axis=1) 连接两个 2-D 数组\n",
    "arr = np.concatenate((arr1, arr2), axis=1)\n",
    "print(arr, arr.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "94fbf1e8",
   "metadata": {},
   "source": [
    "## 使用堆栈函数连接数组\n",
    "堆栈与级联相同，唯一的不同是堆栈是沿着新轴完成的。\n",
    "\n",
    "我们可以沿着第二个轴连接两个一维数组，这将导致它们彼此重叠，即，堆叠（stacking）。\n",
    "\n",
    "我们传递了一系列要与轴一起连接到 concatenate() 方法的数组。如果未显式传递轴，则将其视为 0。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "ba5d6e64",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[[1 2]\n",
      "  [3 4]]\n",
      "\n",
      " [[5 6]\n",
      "  [7 8]]] (2, 2, 2)\n"
     ]
    }
   ],
   "source": [
    "arr = np.stack((arr1, arr2), axis=0)\n",
    "print(arr, arr.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "0c35099c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[[1 2]\n",
      "  [5 6]]\n",
      "\n",
      " [[3 4]\n",
      "  [7 8]]] (2, 2, 2)\n"
     ]
    }
   ],
   "source": [
    "arr = np.stack((arr1, arr2), axis=1)\n",
    "print(arr, arr.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d6a2bfd6",
   "metadata": {},
   "source": [
    "## 沿行堆叠\n",
    "NumPy 提供了一个辅助函数：hstack() 沿行堆叠。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "2f848f24",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2 5 6]\n",
      " [3 4 7 8]] (2, 4)\n"
     ]
    }
   ],
   "source": [
    "arr = np.hstack((arr1, arr2))\n",
    "print(arr, arr.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6e21c9ac",
   "metadata": {},
   "source": [
    "## 沿列堆叠\n",
    "NumPy 提供了一个辅助函数：vstack() 沿列堆叠。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "1e55b60e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2]\n",
      " [3 4]\n",
      " [5 6]\n",
      " [7 8]] (4, 2)\n"
     ]
    }
   ],
   "source": [
    "arr = np.vstack((arr1, arr2))\n",
    "print(arr, arr.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e14f041b",
   "metadata": {},
   "source": [
    "## 沿高度堆叠（深度）\n",
    "NumPy 提供了一个辅助函数：dstack() 沿高度堆叠，该高度与深度相同。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "a3c51658",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[[1 5]\n",
      "  [2 6]]\n",
      "\n",
      " [[3 7]\n",
      "  [4 8]]] (2, 2, 2)\n"
     ]
    }
   ],
   "source": [
    "arr = np.dstack((arr1, arr2))\n",
    "print(arr, arr.shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "81c1213e",
   "metadata": {},
   "source": [
    "# NumPy 数组拆分\n",
    "## 拆分 NumPy 数组\n",
    "拆分是连接的反向操作。\n",
    "\n",
    "连接（Joining）是将多个数组合并为一个，拆分（Spliting）将一个数组拆分为多个。\n",
    "\n",
    "我们使用 array_split() 分割数组，将要分割的数组和分割数传递给它。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 47,
   "id": "9e9e4961",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[array([1, 2]), array([3, 4]), array([5, 6])]\n"
     ]
    }
   ],
   "source": [
    "arr = np.array([1, 2, 3, 4, 5, 6])\n",
    "\n",
    "newarr = np.array_split(arr, 3)\n",
    "\n",
    "print(newarr)\n",
    "#  返回值是一个包含三个数组的数组"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "38eb721d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 2]\n",
      "[3 4]\n",
      "[5 6]\n"
     ]
    }
   ],
   "source": [
    "print(newarr[0])\n",
    "print(newarr[1])\n",
    "print(newarr[2])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 44,
   "id": "2c965345",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[array([1, 2]), array([3, 4]), array([5]), array([6])]\n"
     ]
    }
   ],
   "source": [
    "newarr = np.array_split(arr, 4)\n",
    "\n",
    "print(newarr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "84dc753e",
   "metadata": {},
   "outputs": [
    {
     "ename": "ValueError",
     "evalue": "array split does not result in an equal division",
     "output_type": "error",
     "traceback": [
      "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m",
      "\u001b[1;31mValueError\u001b[0m                                Traceback (most recent call last)",
      "\u001b[1;32m<ipython-input-45-cf3072ca747d>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mnewarr\u001b[0m \u001b[1;33m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msplit\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0marr\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m4\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m\u001b[0;32m      2\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m      3\u001b[0m \u001b[0mprint\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mnewarr\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;32m<__array_function__ internals>\u001b[0m in \u001b[0;36msplit\u001b[1;34m(*args, **kwargs)\u001b[0m\n",
      "\u001b[1;32mD:\\Anaconda3\\envs\\pandascourse\\lib\\site-packages\\numpy\\lib\\shape_base.py\u001b[0m in \u001b[0;36msplit\u001b[1;34m(ary, indices_or_sections, axis)\u001b[0m\n\u001b[0;32m    871\u001b[0m         \u001b[1;32mif\u001b[0m \u001b[0mN\u001b[0m \u001b[1;33m%\u001b[0m \u001b[0msections\u001b[0m\u001b[1;33m:\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    872\u001b[0m             raise ValueError(\n\u001b[1;32m--> 873\u001b[1;33m                 'array split does not result in an equal division') from None\n\u001b[0m\u001b[0;32m    874\u001b[0m     \u001b[1;32mreturn\u001b[0m \u001b[0marray_split\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0mary\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mindices_or_sections\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m    875\u001b[0m \u001b[1;33m\u001b[0m\u001b[0m\n",
      "\u001b[1;31mValueError\u001b[0m: array split does not result in an equal division"
     ]
    }
   ],
   "source": [
    "newarr = np.split(arr, 4)\n",
    "\n",
    "print(newarr)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "b63b7a9b",
   "metadata": {},
   "source": [
    "## 分割二维数组\n",
    "拆分二维数组时，请使用相同的语法。\n",
    "\n",
    "使用 array_split() 方法，传入要分割的数组和想要分割的数目。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "id": "8b9caa8c",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(6, 2)\n",
      "[array([[1, 2],\n",
      "       [3, 4]]), array([[5, 6],\n",
      "       [7, 8]]), array([[ 9, 10],\n",
      "       [11, 12]])]\n"
     ]
    }
   ],
   "source": [
    "arr = np.array([[1, 2], [3, 4], [5, 6], [7, 8], [9, 10], [11, 12]])\n",
    "print(arr.shape)\n",
    "\n",
    "newarr = np.array_split(arr, 3)\n",
    "print(newarr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 52,
   "id": "7c59af71",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(6, 3)\n",
      "[array([[1, 2, 3],\n",
      "       [4, 5, 6]]), array([[ 7,  8,  9],\n",
      "       [10, 11, 12]]), array([[13, 14, 15],\n",
      "       [16, 17, 18]])]\n"
     ]
    }
   ],
   "source": [
    "arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15], [16, 17, 18]])\n",
    "print(arr.shape)\n",
    "\n",
    "newarr = np.array_split(arr, 3)\n",
    "print(newarr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 53,
   "id": "ae203279",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[array([[ 1],\n",
      "       [ 4],\n",
      "       [ 7],\n",
      "       [10],\n",
      "       [13],\n",
      "       [16]]), array([[ 2],\n",
      "       [ 5],\n",
      "       [ 8],\n",
      "       [11],\n",
      "       [14],\n",
      "       [17]]), array([[ 3],\n",
      "       [ 6],\n",
      "       [ 9],\n",
      "       [12],\n",
      "       [15],\n",
      "       [18]])]\n"
     ]
    }
   ],
   "source": [
    "newarr = np.array_split(arr, 3, axis=1)\n",
    "print(newarr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 54,
   "id": "3c0c0a47",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[array([[ 1],\n",
      "       [ 4],\n",
      "       [ 7],\n",
      "       [10],\n",
      "       [13],\n",
      "       [16]]), array([[ 2],\n",
      "       [ 5],\n",
      "       [ 8],\n",
      "       [11],\n",
      "       [14],\n",
      "       [17]]), array([[ 3],\n",
      "       [ 6],\n",
      "       [ 9],\n",
      "       [12],\n",
      "       [15],\n",
      "       [18]])]\n"
     ]
    }
   ],
   "source": [
    "# 另一种解决方案是使用与 hstack() 相反的 hsplit()\n",
    "newarr = np.hsplit(arr, 3)\n",
    "\n",
    "print(newarr)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6e35dd43",
   "metadata": {},
   "source": [
    "# NumPy 数组搜索\n",
    "## 搜索数组\n",
    "您可以在数组中搜索（检索）某个值，然后返回获得匹配的索引。\n",
    "\n",
    "要搜索数组，请使用 where() 方法。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "id": "e2b3afb3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(array([3, 5, 6], dtype=int64),)\n"
     ]
    }
   ],
   "source": [
    "arr = np.array([1, 2, 3, 4, 5, 4, 4])\n",
    "\n",
    "x = np.where(arr == 4)\n",
    "\n",
    "print(x)\n",
    "# 值 4 出现在索引 3、5 和 6"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "id": "81b21332",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(array([1, 3, 5, 7], dtype=int64),)\n"
     ]
    }
   ],
   "source": [
    "arr = np.array([1, 2, 3, 4, 5, 6, 7, 8])\n",
    "# 查找值为偶数的索引\n",
    "x = np.where(arr%2 == 0)\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "id": "8d052647",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(array([0, 2, 4, 6], dtype=int64),)\n"
     ]
    }
   ],
   "source": [
    "# 查找值为奇数的索引\n",
    "x = np.where(arr%2 == 1)\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7e88b94c",
   "metadata": {},
   "source": [
    "## 搜索排序\n",
    "有一个名为 searchsorted() 的方法，该方法在数组中执行二进制搜索，并返回将在其中指定值以维持搜索顺序的索引。\n",
    "\n",
    "假定 searchsorted() 方法用于排序数组。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 69,
   "id": "55ba3e71",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n"
     ]
    }
   ],
   "source": [
    "# 该方法从左侧开始搜索，并返回第一个索引，其中数字 7 不再大于下一个值\n",
    "arr = np.array([6, 8, 9, 10])\n",
    "\n",
    "x = np.searchsorted(arr, 8)\n",
    "\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 68,
   "id": "6fda3322",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "2\n"
     ]
    }
   ],
   "source": [
    "# 从右边开始搜索，并返回第一个索引，其中数字 7 不再小于下一个值\n",
    "x = np.searchsorted(arr, 8, side='right')\n",
    "\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6177170a",
   "metadata": {},
   "source": [
    "## 多个值\n",
    "要搜索多个值，请使用拥有指定值的数组。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 70,
   "id": "dd43bd9d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 2 3]\n"
     ]
    }
   ],
   "source": [
    "arr = np.array([1, 3, 5, 7])\n",
    "\n",
    "x = np.searchsorted(arr, [2, 4, 6])\n",
    "\n",
    "print(x)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "df5d4c4e",
   "metadata": {},
   "source": [
    "# NumPy 数组排序\n",
    "## 数组排序\n",
    "排序是指将元素按有序顺序排列。\n",
    "\n",
    "有序序列是拥有与元素相对应的顺序的任何序列，例如数字或字母、升序或降序。\n",
    "\n",
    "NumPy ndarray 对象有一个名为 sort() 的函数，该函数将对指定的数组进行排序。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 71,
   "id": "a3c51aac",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0 1 2 3]\n"
     ]
    }
   ],
   "source": [
    "arr = np.array([3, 2, 0, 1])\n",
    "\n",
    "print(np.sort(arr))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 72,
   "id": "6141e928",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "['apple' 'banana' 'cherry']\n"
     ]
    }
   ],
   "source": [
    "arr = np.array(['banana', 'cherry', 'apple'])\n",
    "\n",
    "print(np.sort(arr))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 73,
   "id": "99891c70",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[False  True  True]\n"
     ]
    }
   ],
   "source": [
    "arr = np.array([True, False, True])\n",
    "\n",
    "print(np.sort(arr))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "728d8411",
   "metadata": {},
   "source": [
    "## 对 2-D 数组排序\n",
    "如果在二维数组上使用 sort() 方法，则将对两个数组进行排序："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 74,
   "id": "faae794a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[2 3 4]\n",
      " [0 1 5]]\n"
     ]
    }
   ],
   "source": [
    "arr = np.array([[3, 2, 4], [5, 0, 1]])\n",
    "\n",
    "print(np.sort(arr))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ad89bd53",
   "metadata": {},
   "source": [
    "# NumPy 数组过滤\n",
    "## 数组过滤\n",
    "从现有数组中取出一些元素并从中创建新数组称为过滤（filtering）。\n",
    "\n",
    "在 NumPy 中，我们使用布尔索引列表来过滤数组。\n",
    "\n",
    "布尔索引列表是与数组中的索引相对应的布尔值列表。\n",
    "\n",
    "如果索引处的值为 True，则该元素包含在过滤后的数组中；如果索引处的值为 False，则该元素将从过滤后的数组中排除。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 75,
   "id": "c1ed2bbb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[61 63 65]\n"
     ]
    }
   ],
   "source": [
    "arr = np.array([61, 62, 63, 64, 65])\n",
    "\n",
    "x = [True, False, True, False, True]\n",
    "\n",
    "newarr = arr[x]\n",
    "\n",
    "print(newarr)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ecf48e4f",
   "metadata": {},
   "source": [
    "## 创建过滤器数组\n",
    "在上例中，我们对 True 和 False 值进行了硬编码，但通常的用途是根据条件创建过滤器数组。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 76,
   "id": "700a1ebe",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[False, False, True, True, True]\n",
      "[63 64 65]\n"
     ]
    }
   ],
   "source": [
    "# 创建一个仅返回大于 62 的值的过滤器数组\n",
    "arr = np.array([61, 62, 63, 64, 65])\n",
    "\n",
    "# 创建一个空列表\n",
    "filter_arr = []\n",
    "\n",
    "# 遍历 arr 中的每个元素\n",
    "for element in arr:\n",
    "  # 如果元素大于 62，则将值设置为 True，否则为 False：\n",
    "  if element > 62:\n",
    "    filter_arr.append(True)\n",
    "  else:\n",
    "    filter_arr.append(False)\n",
    "\n",
    "newarr = arr[filter_arr]\n",
    "\n",
    "print(filter_arr)\n",
    "print(newarr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 77,
   "id": "44cdb65e",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[False, True, False, True, False, True, False]\n",
      "[2 4 6]\n"
     ]
    }
   ],
   "source": [
    "# 创建一个过滤器数组，该数组仅返回原始数组中的偶数元素\n",
    "arr = np.array([1, 2, 3, 4, 5, 6, 7])\n",
    "\n",
    "# 创建一个空列表\n",
    "filter_arr = []\n",
    "\n",
    "# 遍历 arr 中的每个元素\n",
    "for element in arr:\n",
    "  # 如果元素可以被 2 整除，则将值设置为 True，否则设置为 False\n",
    "  if element % 2 == 0:\n",
    "    filter_arr.append(True)\n",
    "  else:\n",
    "    filter_arr.append(False)\n",
    "\n",
    "newarr = arr[filter_arr]\n",
    "\n",
    "print(filter_arr)\n",
    "print(newarr)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "58f4b23d",
   "metadata": {},
   "source": [
    "## 直接从数组创建过滤器\n",
    "上例是 NumPy 中非常常见的任务，NumPy 提供了解决该问题的好方法。\n",
    "\n",
    "我们可以在条件中直接替换数组而不是 iterable 变量，它会如我们期望地那样工作。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 78,
   "id": "a84ef024",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[False False  True  True  True]\n",
      "[63 64 65]\n"
     ]
    }
   ],
   "source": [
    "arr = np.array([61, 62, 63, 64, 65])\n",
    "\n",
    "filter_arr = arr > 62\n",
    "\n",
    "newarr = arr[filter_arr]\n",
    "\n",
    "print(filter_arr)\n",
    "print(newarr)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 79,
   "id": "9faa7e30",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[False  True False  True False  True False]\n",
      "[2 4 6]\n"
     ]
    }
   ],
   "source": [
    "arr = np.array([1, 2, 3, 4, 5, 6, 7])\n",
    "\n",
    "filter_arr = arr % 2 == 0\n",
    "\n",
    "newarr = arr[filter_arr]\n",
    "\n",
    "print(filter_arr)\n",
    "print(newarr)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.10"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {},
   "toc_section_display": true,
   "toc_window_display": true
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
